package demo1;

import java.util.*;
//此时PriorityQueue的结果是一个小根堆,如果想要结果是一个大根堆,需要修改Student类的compareTo方法或者比较器的compare方法,见包demo3的Test
class Student implements Comparable<Student>{
    public int age;
    public String name;
//    public Student(int age){
//        this.age = age;
//    }

    //只是比较对象的大小关系,返回值为正数/负数/0
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
        //但是这样就写死了，如果要比较姓名就需要进行重新修改代码，而不能直接调用---->此时可以使用equals进行对象的比较,或者使用comparator
    }

    //只是比较是否相等
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
}
//比较器:对类的侵入性较弱
class AgeComparator implements Comparator<Student>{
    public int compare(Student o1, Student o2){
       return o1.age - o2.age;
    }
}
class NameComparator implements Comparator<Student>{
    public int compare(Student o1, Student o2){
        return o1.name.compareTo(o2.name);
    }
}

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "zhangsan";
        s1.age = 10;
        Student s2 = new Student();
        s2.name = "ahangsan";
        s2.age = 12;
        AgeComparator ageComparator = new AgeComparator();
        System.out.println(ageComparator.compare(s1, s2));
        NameComparator nameComparator = new NameComparator();
        System.out.println(nameComparator.compare(s1, s2));
    }
    public static void main3(String[] args) {
        //此时只是重写了compareTo方法.根据显示经验，不考虑一个班有人同名的情况，那么如果找到两个人的name都为zhangsan，
        // 那么就代表是同一个人，但是此时就不能实现。如果将name也进行compareTo的重写，那么name可以解决
        // ，但是如果引入更多的属性此时的compareTo还是需要进行手动修改
        Student s1 = new Student();
        s1.name = "zhangsan";
        Student s2 = new Student();
        s2.name = "zhangsan";
        Student s3 = new Student();
        s3.name = "lisi";
        System.out.println(s1.compareTo(s2));//此时输出0,表示相等,因为此时s1和s2的age都为0
        System.out.println(s1.compareTo(s3));//此时输出0,表示相等,因为此时s1和s3的age都为0(只写了关于student类的age比较,所以只会根据age来看大小)

        System.out.println(s1 == s2);//此时输出false,比较的是地址
        System.out.println(s1.equals(s2));//此时输出true


    }
    public static void main2(String[] args) {
        //此时Studnet类的书写方式为：
        /*
            class Student{
                public int age;
                public String name;
                public Student(int age){
                    this.age = age;
                }
            }
         */
        //此时运行就会报错，因为PriorityQueue里面只能存放可以进行比较的对象，而定义的Student类没有实现Comparable类，
        // 而不能进行对象的比较：这主要是因为再PriorityQueue底层的offer方法中，实现了siftUpComparable方法，该方法会进行强制类型转换，
        // 转换为Comparable类型，但是Student类没有实现Comparable接口，故无法进行该强制类型转换，
        // 就会报错：demo1.Student cannot be cast to java.lang.Comparable
        PriorityQueue<Student> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(new Student());
        priorityQueue.offer(new Student());
    }
    public static void main1(String[] args) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
        //因为priorityQueue实现了Queue,所以也可以进行如下的定义
        Queue<Integer> priorityQueue1 = new PriorityQueue<>();
        //priorityQueue有很多种构造方法
        //比如：public PriorityQueue(Collection<? extends E> c) ，这里？表示里面的集合是c，
        //也可以是c的子类。可以将？整个元素传到PriorityQueue里面
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(100);
        PriorityQueue<Integer> priorityQueue2 = new PriorityQueue<>(list);
        //PriorityQueue默认存放的是小根堆，所以再进行poll的时候会将最小值输出
        priorityQueue2.offer(5);
        priorityQueue2.offer(3);
        priorityQueue2.offer(9);
        System.out.println(priorityQueue2.poll());//此时会输出1，因为list也完全放到了PriorityQueue里面
        System.out.println(priorityQueue2.poll());//输出3
        System.out.println(priorityQueue2.poll());//输出5
    }
}
